﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using theeg.GeometryWpf;

namespace theeg.GraphWpf.Models
{
    public class Node : NotifyingObject, INode
    {
        private ComputationalRectangle _boundingBox;

        private double _left;
        public double Left
        {
            get { return _left; }
            set
            {
                SetNotifyingField(ref _left, value, "CenterX");
                _boundingBox = null;
            }
        }

        private double _top;
        public double Top
        {
            get { return _top; }
            set
            {
                SetNotifyingField(ref _top, value, "CenterY");
                _boundingBox = null;
            }
        }

        private string _text;
        public string Text
        {
            get { return _text; }
            set { SetNotifyingField(ref _text, value, "Text"); }
        }

        private Brush _stroke;
        public Brush Stroke
        {
            get { return _stroke; }
            set { SetNotifyingField(ref _stroke, value, "Stroke"); }
        }

        private Brush _highlight = new SolidColorBrush(Colors.Red);
        public Brush Highlight
        {
            get { return _highlight; }
            set { SetNotifyingField(ref _highlight, value, "Highlight"); }
        }

        private Brush _background = new SolidColorBrush(Colors.White);
        public Brush Background
        {
            get { return _background; }
            set { SetNotifyingField(ref _background, value, "Background"); }
        }

        private Brush _foreground = new SolidColorBrush(Colors.Black);
        public Brush Foreground
        {
            get { return _foreground; }
            set { SetNotifyingField(ref _foreground, value, "Foreground"); }
        }

        private double _width = 100.0;
        public double Width
        {
            get { return _width; }
            set
            {
                SetNotifyingField(ref _width, value, "Width");
                _boundingBox = null;
            }
        }

        private double _height = 100.0;
        public double Height
        {
            get { return _height; }
            set
            {
                SetNotifyingField(ref _height, value, "Height");
                _boundingBox = null;
            }
        }

        public Point Center
        {
            get
            {
                return new Point(_left + _width * 0.5, _top + _height * 0.5);
            }
        }

        private NodeShape _nodeShape;
        public NodeShape NodeShape
        {
            get { return _nodeShape; }
            set { SetNotifyingField(ref _nodeShape, value, "NodeShape"); }
        }

        private object _dataObject;

        public object DataObject
        {
            get { return _dataObject; }
            set { SetNotifyingField(ref _dataObject, value, "DataObject"); }
        }

        private bool _isHighlighted;
        public bool IsHighlighted
        {
            get { return _isHighlighted; }
            set
            {
                if (value != _isHighlighted)
                {
                    _isHighlighted = value;
                    RaisePropertyChanged("IsHighlighted");
                }
            }
        }

        public int GenericMarker { get; set; }

        private readonly List<Transition> _incomingEdges = new List<Transition>();

        public List<Transition> IncomingEdges
        {
            get { return _incomingEdges; }
        }

        private readonly List<Transition> _outgoingEdges = new List<Transition>();

        public List<Transition> OutgoingEdges
        {
            get { return _outgoingEdges; }
        }

        public ComputationalRectangle GetBoundingBox()
        {
            return _boundingBox ?? (_boundingBox = new ComputationalRectangle(Left, Top, Left + Width, Top + Height));
        }

        public ShapeOverlapping Contains(ComputationalShape range)
        {
            return range.Contains(((IHilbertTreeNode)this).GetBoundingBox());
        }

        public double GetDistanceFrom(Point pt)
        {
            throw new NotImplementedException();
        }

        public double GetLevelOfDetailFactor()
        {
            throw new NotImplementedException();
        }

        internal void DeleteEdge(Transition edge)
        {
            if (IncomingEdges.Contains(edge))
            {
                IncomingEdges.Remove(edge);
            }
            if (OutgoingEdges.Contains(edge))
            {
                OutgoingEdges.Remove(edge);
            }
        }

        public int Category { get { return 0; } }

        public Visibility Visibility { get; set; }

        public double CenterX
        {
            get { return Left + 0.5 * Width; }
            set { Left = value - 0.5 * Width; }
        }

        public double CenterY
        {
            get { return Top + 0.5 * Height; }
            set { Top = value - 0.5 * Height; }
        }
    }
}
